﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BankAccountNS;

namespace BankTest
{
    // Nous ne travaillons que sur la fct Debit de la classe BankAccount

    [TestClass]
    public class BankAccountTests
    {        
        [TestMethod]
        public void Debit_WithValidAmount_UpdatesBalance()
        {
            // arrange
            double beginningBalance = 11.99;
            double debitAmount = 4.55;
            double expected = 7.44;
            BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

            // act
            account.Debit(debitAmount);

            // assert
            double actual = account.Balance;

            // Vérification 
            Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");      // Compare contenue primaire ou objet (surchrger Equals)
            Assert.AreEqual<double>(expected, actual, "Account not debited correctly");     // Compare contenue primaire ou objet de deux type T (surchrger Equals)
            Assert.AreNotEqual(expected, actual+1, 0.001, "Account not debited correctly");   // Compare contenue primaire ou objet (surchrger Equals)
            Assert.AreNotEqual<double>(expected, actual+1, "Account not debited correctly");  // Compare contenue primaire ou objet de deux type T (surchrger Equals)
            //Assert.AreSame(expected, expected, "Account not debited correctly");              // Compare référence
            Assert.AreNotSame(expected, actual, "Account not debited correctly");           // Compare référence
            //Assert.Equals(expected, actual);                                               // NE PAS UTILISER // Compare Seulement des objets
           
            Assert.ReferenceEquals(expected, actual);                                       // Compare référence
            Assert.ReplaceNullChars("Account not debited correctly");                       // Compare référence

            Assert.IsTrue(actual == expected, "Account not debited correctly");
            Assert.IsFalse(actual != expected, "Account not debited correctly");
            Assert.IsInstanceOfType(actual, typeof(double));
            Assert.IsNotInstanceOfType(actual, typeof(int));
            Assert.IsNotNull(actual);
            Assert.IsNull(null);

            Assert.Inconclusive("Finish");                                                  // Message d'avertissement

            // Assert.Fail( ... ) // Voir plus bas
        }

        //unit test method
        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))] // Vérification que le test lève bien se type d'exception
        public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
        {
            // arrange
            double beginningBalance = 11.99;
            double debitAmount = -100.00;
            BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

            // act
            account.Debit(debitAmount);

            // assert is handled by ExpectedException
        }

        //unit test method
        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))] // Vérification que le test lève bien se type d'exception
        public void Debit_WhenAmountIsMoreThanZero_ShouldThrowArgumentOutOfRange()
        {
            // arrange
            double beginningBalance = 11.99;
            double debitAmount = 100.00;
            BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

            // act
            account.Debit(debitAmount);

            // assert is handled by ExpectedException
        }

        // Le but du test est de voir si l'exception est levée
        [TestMethod]
        public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange()
        {
            // arrange
            double beginningBalance = 11.99;
            double debitAmount = -20.0;
            BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

            // act
            try
            {
                account.Debit(debitAmount);
            }
            catch (ArgumentOutOfRangeException e)
            {
                // assert
                StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
                return;
            }

            // Provoque l'échec du test : car ici si l'exception est levé alors elle sera traité sinon on arrive là
            Assert.Fail("No exception was thrown.");
        }        
    }
}
